import re


from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework_jwt.settings import api_settings
from celery_tasks.email.tasks import send_verify_email
from users.models import User, Address
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from django.conf import settings
class VerifyEmailSerializer(serializers.ModelSerializer):
    """
    验证邮箱序列化器
    """
    class Meta:
        model = User
        fields = ('id', 'email_active')
        extra_kwargs = {
            'email_active': {
                'required': True
            }
        }

    def update(self, instance, validated_data):
        instance.email_active = validated_data['email_active']
        instance.save()




class EmailSerializer(serializers.ModelSerializer):
    """
    邮箱序列化器
    """
    class Meta:
        model = User
        fields = ('id', 'email')
        extra_kwargs = {
            'email': {
                'required': True
            }
        }

    def update(self, instance, validated_data):
        instance.email = validated_data['email']
        instance.save()

        # 生成验证链接
        verify_url = instance.generate_verify_email_url()
        send_verify_email(instance.email, verify_url)
        print("验证链接", verify_url)
        # 发送验证邮件
        # send_verify_email.delay(self.request.user.email, verify_url)
        # subject = "美多商城邮箱验证"
        # html_message = '<p>尊敬的用户您好！</p>' \
        #                '<p>感谢您使用美多商城。</p>' \
        #                '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
        #                '<p><a href="%s">%s<a></p>' % (instance.email, verify_url, verify_url)
        # send_mail(subject, "XXXXX", settings.EMAIL_FROM, [instance.email], html_message=html_message)

        # print("BB", verify_url)
        # print("CC", instance.email)
        return instance


class UserSerializer(ModelSerializer):

    class Meta:
        model=User
        fields=('id', 'username', 'mobile', 'email', 'email_active')


class UpdataDefaultAddressSerializer(ModelSerializer):
    default_address = serializers.StringRelatedField(read_only=True)
    default_address_id = serializers.IntegerField(label='默认地址ID', required=True)

    class Meta:
        model = User
        fields = ('id', 'default_address_id','default_address')


class CreateUserSerializer(ModelSerializer):
    """
    注册用户使用的序列化器
    要校验的属性: username, password , password2, mobile, allow, sms_code
    要返回的属性: id, username, mobile
    """
    # 新增需要校验的字段
    password2 = serializers.CharField(label='确认密码', write_only=True)
    sms_code = serializers.CharField(label='短信验证码', max_length=6, write_only=True)
    allow = serializers.BooleanField(label='同意用户协议', write_only=True)
    token = serializers.CharField(label='登录状态token', read_only=True)  # 增加token字段

    def validate_mobile(self, value):
        """
        验证单个字段
        验证手机号
        该方法必须有返回值
        """
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')
            # return Response({'message':'xxxxxx'}, status=400)
        return value

    def validate_allow(self, value):
        """检验用户是否同意协议"""
        if not value:
            raise serializers.ValidationError('请同意用户协议')
        return value

    def validate(self,attrs):

        if attrs['password'] != attrs["password2"]:
            raise serializers.ValidationError("两次密码不一样")
        mobile = attrs.get('mobile')
        strict_redis = get_redis_connection('sms_codes')
        real_sms_code = strict_redis.get("sms_%s" % mobile)
        sms_code = attrs.get('sms_code')
        if real_sms_code is None:  # 判断验证码是否过期，　已经超过了过期时间
            raise ValidationError('无效的短信验证码')

        if sms_code != real_sms_code.decode():
            raise ValidationError('短信验证码不正确')

        return attrs

    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data.get('username'),
            password=validated_data.get('password'),
            mobile=validated_data.get('mobile'),
        )

        # 补充生成记录登录状态的token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token
        return user

    extra_kwargs = {
        'username': {
            'min_length': 5,
            'max_length': 20,
            'error_messages': {
                'min_length': '仅允许5-20个字符的用户名',
                'max_length': '仅允许5-20个字符的用户名',
            }
        },
        'password': {
            'write_only': True,
            'min_length': 8,
            'max_length': 20,
            'error_messages': {
                'min_length': '仅允许8-20个字符的密码',
                'max_length': '仅允许8-20个字符的密码',
            }
        }
    }

    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'password', 'password2',
                  'sms_code', 'allow', 'token','default_address_id')

class AddressUserSerializer(ModelSerializer):
    province = serializers.StringRelatedField(read_only=True)
    city = serializers.StringRelatedField(read_only=True)
    district = serializers.StringRelatedField(read_only=True)

    # user = serializers.StringRelatedField(read_only=True)

    province_id = serializers.IntegerField(label='省ID', required=True)
    city_id = serializers.IntegerField(label='市ID', required=True)
    district_id = serializers.IntegerField(label='区ID', required=True)
    user_id = serializers.IntegerField(label='用户ID', required=True)

    class Meta:
        model = Address
        exclude = ('user','is_deleted', 'create_time', 'update_time')

    def validate_mobile(self, value):
        """检验用户手机号码"""
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式错误')
            # return Response({'message':'xxxxxx'}, status=400)
        return value




    '''
    １　序列化器中的字段直接影响使用其的类视图，所有字段问题皆在序列化器中的字段属性设置中
    ２　序列化器中可以添加校验方法validate对器自身字段除属性校验外的其他验证，这些校验将在使用序列化器
    时进行，
    ３　序列化器三大区：１　模型类自有全部字段
    　　　　　　　　　　２　序列化器中添加的字段,特别是关系字段的处理
    　　　　　　　　　　３　序列化器中包含使用的字段及自定义校验方法
    '''

